Functions and Modules

Computer Science – XI · Chapter 7 · Questions and Answers

Introduction

1. Why is a large program broken into smaller parts? What is modularisation?

As problems grow, programs become longer, harder to read, understand and maintain. Breaking a large program into smaller, manageable subprograms solves this. The process of breaking a large problem into smaller, simpler sub-problems is called modularisation. Code for a major subtask is placed in a module, and code for smaller subtasks is placed in functions.

2. What are the advantages of using functions?
  • Code reusability: a function such as "total marks" can be used many times in different parts of a program.
  • Less duplication of code, so smaller code size.
  • Programs become more manageable, easier to read, test and maintain.
3. Classify functions in Python. What are arguments and return values?

Functions are classified as built-in, imported and user-defined. A function receives zero or more values as inputs, called arguments (sometimes parameters), and returns zero or more output values, called return values.

7.2 Built-in functions

4. What are built-in functions? Where are they available?

Predefined functions that can be used without defining them. They are part of the Python standard library.

5. What are type conversion functions? Explain int(), float(), str() and bool().

Type conversion functions accept an argument of one data type and return an equivalent value of another type.

FunctionActionExamples
int()Converts a numeric expression, or a string of whole numbers, to an integer; returns the integer part. A string with non-numeric characters gives an error.int(7.9) → 7; int("25") → 25
float()Converts a numeric expression or numeric string to float. Non-numeric strings give an error.float(5) → 5.0; float("2.5") → 2.5
str()Converts any object to its string representation.str(65) → '65'
bool()Returns False for False, None, 0, empty string or any empty collection; True otherwise.bool(0) → False; bool("a") → True
6. Give the output and data type: (a) int(-123) (b) float("123") (c) str("65") (d) bool("None")
CodeOutputType
(a) int(-123)-123int
(b) float("123")123.0float
(c) str("65")'65'str
(d) bool("None")True (it is a non-empty string, not the value None)bool
7. What does eval() do? What are its limitations?

eval() takes a string containing a valid Python expression and returns the result of evaluating it. The return type depends on the result, e.g. eval("3 + 4 * 2") gives 11. It works only with expressions, not with statements like if, for or while.

8. Execute and explain: (a) eval("45 + True") (b) eval(True) (c) eval(34) (d) abs(4+-7)
CodeResult
(a)46. The string is a valid expression and True has the value 1.
(b)TypeError. eval() needs a string (or code object), not a Boolean.
(c)TypeError. The argument is an integer, not a string.
(d)3. 4 + (–7) = –3 and its absolute value is 3.
9. Explain max() and min(). How are strings compared?

They return the largest and smallest value from a group of values (list, tuple, set, or comma-separated numbers or strings). The return type matches the elements. If the elements cannot be compared (e.g. a number and a string), an error occurs.

Strings are compared in dictionary order and the comparison is case sensitive: all uppercase letters come before lowercase letters because their Unicode values are smaller.

max(4, 9, 2)          # 9
min([5, 1, 8])        # 1
max("apple", "Zebra") # 'apple' (lowercase 'a' > uppercase 'Z')
10. Explain abs(), type(), len() and id().
  • abs(x): returns the absolute (positive) value of a number, e.g. abs(-7) → 7. A non-numeric argument gives an error.
  • type(x): returns the data type of a variable, literal, expression or object, e.g. type(5.2) → <class 'float'>.
  • len(x): returns the number of characters in a string or number of items in a list, tuple, set or dictionary, e.g. len("Python") → 6.
  • id(x): returns a unique number representing the memory reference of the object. Two variables referring to the same object have the same id.
11. Explain round(n, d) with examples. What is banker's rounding?

round(n, d) rounds the number n to d decimal digits. If d is omitted, it rounds to the nearest integer. If d is negative, it rounds to the nearest power of ten: round(2673.23, -2) gives 2700.

round(3.14159, 2)   # 3.14
round(7.6)          # 8
round(2673.23, -2)  # 2700.0

Banker's rounding (round half to even): when a value is exactly halfway (.5), it is rounded to the nearest even number: round(2.5) gives 2 and round(3.5) gives 4. This balances rounding up and down, giving more accurate results over a large number of calculations.

12. Write code to accept comma-separated integers, convert them to numbers, and find the length, minimum and maximum.
s = input("Enter integers separated by commas: ")
nums = [int(x) for x in s.split(",")]
print("Length =", len(nums))
print("Minimum =", min(nums))
print("Maximum =", max(nums))

Input 4,9,2 gives length 3, minimum 2, maximum 9.

13. Write code to accept comma-separated floats, convert them to numbers, and find the data type and ID.
s = input("Enter float values separated by commas: ")
nums = [float(x) for x in s.split(",")]
print("Data type:", type(nums))
print("ID:", id(nums))

The type is <class 'list'>; the ID is a unique number that differs on each run. To see the type of the values themselves use type(nums[0]) (float).

7.3 Imported functions

14. What is a module? How are related functions grouped?

A module is a file containing code (variables, functions and even other imported modules). Related functions are grouped into modules according to their purpose, e.g. math (sqrt, etc.), statistics, string, random.

15. How can modules be imported? What is an alias?
  • Entire module: import math or import math, statistics. Functions are accessed with the dot operator: math.sqrt(16).
  • Alias: a shorter name given with as: import statistics as stat, then stat.mean(data).
  • Selected functions: from math import sqrt or from math import sqrt, pow, cos. They are then used without the module name: sqrt(16).
  • All functions: from math import *.

Importing selected functions avoids loading the whole module, which keeps the translated code smaller.

16. Explain the functions of the math module: sqrt, pow, ceil, floor, fabs, sin, cos.
FunctionDescriptionExample
sqrt(x)Square root; a negative argument gives a run-time errormath.sqrt(25) → 5.0
pow(x, y)x raised to y; result is always floatmath.pow(2, 3) → 8.0
ceil(x)Smallest integer ≥ xmath.ceil(4.2) → 5
floor(x)Largest integer ≤ xmath.floor(4.8) → 4
fabs(x)Absolute value (as float)math.fabs(-3) → 3.0
sin(x)Sine of x, x in radiansmath.sin(0) → 0.0
cos(x)Cosine of x, x in radiansmath.cos(0) → 1.0
17. Find the output and return type: (a) math.sqrt(-25) (b) math.pow(2,3) (c) math.ceil(-47.7) (d) math.floor(-23.2)
CodeResult
(a)ValueError: math domain error. The square root of a negative number is not defined in math.
(b)8.0 (float)
(c)-47 (int). The smallest integer ≥ –47.7.
(d)-24 (int). The largest integer ≤ –23.2.
18. Explain the functions of the statistics module.

Import with import statistics; it is part of the standard library. The functions work on a group of values (list, tuple, set).

FunctionDescription
mean(data)Arithmetic mean (average)
median(data)Middle value of the sorted data
mode(data)Most frequently occurring value
variance(data)Sample variance; measures how far values are spread from the mean
stdev(data)Sample standard deviation; the square root of variance, in the same units as the data
import statistics
d = [2, 4, 4, 4, 5, 5, 7, 9]
statistics.mean(d)    # 5.0
statistics.median(d)  # 4.5
statistics.mode(d)    # 4
19. Write code to find the next higher integer of the mean, median and mode of a list.
import math, statistics
data = list(map(float, input("Enter values separated by spaces: ").split()))
print("Mean   :", math.ceil(statistics.mean(data)))
print("Median :", math.ceil(statistics.median(data)))
print("Mode   :", math.ceil(statistics.mode(data)))

math.ceil() gives the next higher integer.

20. Write code to find the mean of a list correct to two decimal places.
import statistics
data = list(map(float, input("Enter values separated by spaces: ").split()))
print("Mean =", round(statistics.mean(data), 2))
21. Write code to find the standard deviation of a list and the difference of each element from it.
import statistics
data = list(map(float, input("Enter values separated by spaces: ").split()))
sd = statistics.stdev(data)
print("Standard deviation =", sd)
for x in data:
    print(x, "-", sd, "=", x - sd)

7.4 User-defined functions

22. How is a user-defined function defined? Explain the syntax.
def function_name(argument_list):
    function_statement1
    function_statement2

def is the keyword that starts the definition. The function name follows the identifier rules of Chapter 5. The argument (parameter) list names the variables through which values are passed in. The body is indented. A return statement sends a result back to the caller; it is used only if there is a value to return.

def welcome():
    print("Welcome to Python functions")
23. How is a function called? Explain the flow of execution.

A function is called by writing its name with brackets, e.g. welcome(). A function runs only when called, and it must be defined before it is called.

Execution begins at the first statement outside all function definitions. Function definitions are processed but skipped. When a call is found, control transfers to the first statement in the function and runs until its last statement or a return. Control then returns to the point of the call and execution continues in the calling program.

24. Differentiate between actual and formal arguments. Write a function to calculate simple interest.

Actual arguments are the values or variables in the function call. Formal arguments are the variables in the function definition that receive them.

def interest(P, N, R):       # P, N, R: formal arguments
    si = P * N * R / 100
    return si

principal = 1000
years = 2
rate = 10
simple = interest(principal, years, rate)   # actual arguments
print("Simple Interest is:", simple)

Output: Simple Interest is: 200.0

25. What is the role of return? What is returned if there is no return statement?

return ends the execution of the function and sends the specified value back to the calling statement. If a function has no return, or uses return without a value, it returns None, which represents absence of a value.

26. Write a function to find the factorial of a number. What happens if 5.5 is passed?
def factorial(n):
    f = 1
    for i in range(1, n + 1):
        f = f * i
    return f

print(factorial(5))   # 120

Passing 5.5 gives an error because range() accepts only integers. This shows why validating the type of arguments is important.

27. How can a function return multiple values? Give an example comparing simple and compound interest.

Values separated by commas in the return statement are automatically packed into a tuple. The caller unpacks them into variables.

def interest(P, N, R):
    si = P * N * R / 100
    ci = P * (1 + R / 100) ** N - P
    return si, ci

simple, compound = interest(1000, 2, 10)
print("Simple interest:", simple)      # 200.0
print("Compound interest:", compound)  # 210.0 (approximately)
28. Write a function that does not return a value.
def interest(P, N, R):
    si = P * N * R / 100
    print("Simple Interest is:", si)   # result displayed inside the function

interest(1000, 2, 10)

It returns None by default.

7.5 Types of arguments

29. What are positional arguments?

Arguments passed in the same order (position) as in the function definition. In interest(1000, 2, 10), 1000 goes to P, 2 to N and 10 to R.

30. What are default arguments? What is the rule about their position?

A default argument has a value assigned in the function definition using =, used when the call does not supply that value. Default arguments must be the rightmost arguments in the definition.

def interest(P, N, R=10):
    print("Simple Interest is:", P * N * R / 100)

interest(1000, 2)       # Simple Interest is: 200.0  (R = 10)
interest(1000, 2, 12)   # Simple Interest is: 240.0  (given value 12 is used)
31. What are keyword arguments? What rule applies when mixing them with positional arguments?

Keyword arguments are passed by naming each formal argument along with its value, so the order does not matter and the code is more readable:

interest(R=12, P=1000, N=2)
interest(1000, R=12, N=2)

Positional arguments in a call must come first (to the left). The sep and end of print() are examples of keyword arguments.

32. What are variable length arguments? Write a function average() using them.

Prefixing a parameter with * lets the function accept any number of arguments. They are stored in a tuple.

def average(*numbers):
    total = 0
    for n in numbers:
        total = total + n
    return total / len(numbers)

print(average(10, 20, 30))        # 20.0
print(average(5, 7, 9, 11, 13))   # 9.0
33. Differentiate between the four types of arguments.
TypeKey point
PositionalMatched by order
DefaultValue given in the definition; must be rightmost
KeywordMatched by name; order does not matter
Variable lengthMarked with *; any number of values, stored in a tuple

User-defined functions – Let us do

34. Function that returns the sum of the digits of an integer.
def sum_digits(n):
    total = 0
    while n > 0:
        total = total + n % 10
        n = n // 10
    return total

print(sum_digits(1234))   # 10
35. Function that returns n if it is prime, otherwise None; display the primes between two numbers.
def prime(n):
    if n < 2:
        return None
    for i in range(2, n):
        if n % i == 0:
            return None
    return n

a = int(input("Enter lower limit: "))
b = int(input("Enter upper limit: "))
for k in range(a, b + 1):
    if prime(k) is not None:
        print(k, end=" ")
36. Function reverse(n) without strings; check for a palindrome.
def reverse(n):
    rev = 0
    while n > 0:
        rev = rev * 10 + n % 10
        n = n // 10
    return rev

num = int(input("Enter a number: "))
if reverse(num) == num:
    print("Palindrome")
else:
    print("Not a palindrome")
37. Function to convert Celsius to Fahrenheit.
def to_fahrenheit(c):
    return (9 / 5) * c + 32

print(to_fahrenheit(100))   # 212.0
38. Function that takes dd, mm, yyyy and returns whether the date is valid.
def valid_date(d, m, y):
    if y <= 0 or m < 1 or m > 12 or d < 1:
        return False
    leap = (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
    if m == 2:
        days = 29 if leap else 28
    elif m in (4, 6, 9, 11):
        days = 30
    else:
        days = 31
    return d <= days

print(valid_date(29, 2, 2024))   # True
print(valid_date(31, 4, 2025))   # False
39. Function to convert paise into rupees and paise and return both.
def convert(p):
    return p // 100, p % 100

rs, ps = convert(575)
print("Rs.", rs, "Ps.", ps)    # Rs. 5 Ps. 75
40. Function that returns the number of even digits and odd digits of an integer.
def count_digits(n):
    even = odd = 0
    while n > 0:
        if (n % 10) % 2 == 0:
            even = even + 1
        else:
            odd = odd + 1
        n = n // 10
    return even, odd

e, o = count_digits(12345)
print("Even:", e, "Odd:", o)   # Even: 2 Odd: 3
41. Function that analyses temperatures: highest, lowest, mean and number of days above the mean.
def analyse(temps):
    high = max(temps)
    low = min(temps)
    mean = sum(temps) / len(temps)
    above = 0
    for t in temps:
        if t > mean:
            above = above + 1
    return high, low, mean, above

h, l, m, a = analyse([31, 33, 30, 35, 34])
print(h, l, m, a)    # 35 30 32.6 3
42. Function that returns the first and last digit of an integer.
def first_last(n):
    last = n % 10
    while n >= 10:
        n = n // 10
    return n, last

f, l = first_last(7284)
print("First:", f, "Last:", l)   # First: 7 Last: 4
43. Function that accepts an integer less than 10 and prints the pattern (1 / 1 2 / 1 2 3 / 1 2 3 4 for 4).
def pattern(n):
    for i in range(1, n + 1):
        for j in range(1, i + 1):
            print(j, end=" ")
        print()

pattern(4)

7.6 Scope rules

44. What are scope rules?

Scope rules determine the region of a program where a reference (variable) remains valid. A reference assigned inside a function is valid only within that function. References assigned outside all functions are generally valid throughout the program, unless overridden inside a function.

45. Explain local scope with an example.

A variable created inside a function has local scope and can be used only inside that function.

def test():
    x = 10
    print("Inside function:", x)

test()
print(x)    # NameError: name 'x' is not defined

Accessing x outside the function gives an error.

46. Explain global scope with an example.

A variable defined outside all functions has global scope and can be read from anywhere, including inside functions.

x = 50
def show():
    print("Inside function:", x)

show()            # Inside function: 50
print("Outside:", x)   # Outside: 50
47. What is overriding of a global variable? How can it be bypassed?

If a variable that exists globally is assigned inside a function, a new local variable is created that overrides the global one inside the function; the global value is unchanged.

x = 50
def change():
    x = 100
    print("Inside:", x)    # 100
change()
print("Outside:", x)      # 50

To use and modify the global variable instead, declare it with the global keyword:

x = 50
def change():
    global x
    x = 100
change()
print(x)    # 100

7.7 Recursive functions

48. What is recursion? What are the base case and the recursive part?

Recursion is a technique in which a function solves a problem by calling itself on smaller versions of the same problem. A function that calls itself is a recursive function.

  • Base case: the condition that stops the recursion, where the problem is simple enough to solve directly. Without it, the function would call itself indefinitely and Python reports an error.
  • Recursive part: the part where the function calls itself with modified arguments, moving closer to the base case.
49. Write a recursive function for factorial and trace factorial(5).
def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))   # 120

Since n! = n × (n–1)! and 1! = 1:

factorial(5) = 5 × factorial(4) = 5 × 4 × factorial(3) = 5 × 4 × 3 × factorial(2) = 5 × 4 × 3 × 2 × factorial(1). With factorial(1) = 1, the values return: 2 × 1 = 2; 3 × 2 = 6; 4 × 6 = 24; 5 × 24 = 120.

50. Write recursive functions for the sum of digits and the sum of the first n natural numbers.
def sumofdigits(n):
    if n == 0:                 # base case
        return 0
    return n % 10 + sumofdigits(n // 10)

def sumnatural(n):
    if n == 1:                 # base case
        return 1
    return n + sumnatural(n - 1)

print(sumofdigits(1234))   # 10
print(sumnatural(5))       # 15
51. Print n Fibonacci numbers using a recursive function. Explain how it works.
def fibonacci(n):
    if n == 0 or n == 1:      # base cases
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

for i in range(6):
    print(fibonacci(i), end=" ")    # 0 1 1 2 3 5

Each term is the sum of the two preceding terms; the base cases are fibonacci(0) = 0 and fibonacci(1) = 1. For example, fibonacci(3) = fibonacci(2) + fibonacci(1) = (1 + 0) + 1 = 2.

52. What are the advantages and disadvantages of recursion?

Advantages: easier to write and understand for problems that naturally divide into smaller subproblems; shorter, cleaner, more readable code.

Disadvantages: uses more memory and may be slower than loops.

53. Recursive function to count the digits of an integer without converting to a string.
def count_digits(n):
    if n < 10:
        return 1
    return 1 + count_digits(n // 10)

print(count_digits(48215))   # 5
54. Recursive function to compute xn without pow() or loops.
def power(x, n):
    if n == 0:
        return 1
    return x * power(x, n - 1)

print(power(2, 5))   # 32

Uses xn = x × xn–1 with base case x0 = 1.

55. Recursive function returning the sum of the divisors of an integer.
def sum_divisors(n, i=1):
    if i > n:
        return 0
    if n % i == 0:
        return i + sum_divisors(n, i + 1)
    return sum_divisors(n, i + 1)

print(sum_divisors(12))   # 28  (1+2+3+4+6+12)
56. Recursive functions to count the even digits and to sum the even digits of an integer.
def count_even(n):
    if n == 0:
        return 0
    d = n % 10
    if d % 2 == 0:
        return 1 + count_even(n // 10)
    return count_even(n // 10)

def sum_even(n):
    if n == 0:
        return 0
    d = n % 10
    if d % 2 == 0:
        return d + sum_even(n // 10)
    return sum_even(n // 10)

print(count_even(24681))   # 4
print(sum_even(24681))     # 20

7.8–7.9 Modules and program hierarchy

57. What is a user-defined module? Create and use a calculator module.

A user-defined module is a Python file (extension .py) containing definitions of functions, variables or classes.

# calculator.py
def add(a, b):
    return a + b

def divide(a, b):
    return a / b
# main program
import calculator
print("Addition:", calculator.add(10, 15))     # Addition: 25

from calculator import divide
print("Division:", divide(20, 5))              # Division: 4.0
58. What are the advantages of using modules?

Breaking a program into modules gives cleaner, maintainable and reusable code, and lets the same functions be used in many programs.

59. Explain the hierarchical building blocks of Python programs.
LevelDescription
FunctionA block of organised, reusable code that performs a specific task
ModuleA file containing functions, classes or variables; used through import
PackageA collection of related modules in a folder. It must contain a file named __init__.py (can be empty). Examples: NumPy, Pandas, Matplotlib
LibraryA collection of built-in and external modules and packages providing ready-to-use functionality (mathematics, data science, web development)
60. Fill in the blanks / one-word answers.
  • The keyword used to define a function: def.
  • The keyword used to bring a module into a program: import.
  • Default return value of a function without return: None.
  • Default arguments must be the ______ arguments: rightmost.
  • Prefix used for variable length arguments: *.
  • Keyword to modify a global variable inside a function: global.
  • File required to make a folder a package: __init__.py.
  • Function that finds the memory reference of an object: id().